Pla Clima

El canvi climàtic és una realitat i està ocasionat per l’ésser humà. Ja tenim evidències dels seus impactes i cal actuar per a fer-hi front.

Les ciutats són especialment vulnerables, ja que concentren la majoria de la població mundial i és on l’energia es consumeix de manera més intensiva, generant el 70% de les emissions de gasos amb efecte d’hivernacle.

Barcelona és una ciutat mediterrània, que consumeix poca energia i genera poques emissions per càpita en relació a altres ciutats similars, però encara té molt camí per recórrer, ja que té una elevada dependència de recursos fòssils i nuclears.

Els efectes del canvi climàtic podrien presentar riscos en termes de salut i benestar de les persones (onades de calor), de seguretat (garantia de subministrament d’aigua i d’energia, vulnerabilitat de les infraestructures, risc d’incendis..) i en l’entorn natural que cal preveure i prevenir a nivell global.

Amb motiu de la celebració a París de la COP21, la 21a Conferència de les Parts de la Convenció Marc de les Nacions Unides sobre el Canvi Climàtic, i en el marc del Compromís Ciutadà per la Sostenibilitat, Barcelona va concretar un Compromís de Barcelona pel Clima, en què es comprometia a reduir les emissions de gasos em efecte hivernacle un 40% al 2030 en relació al 2005 i augmentar 1,6km2 de verd urbà com a mesura d’adaptació.

Ajuntament i ciutadania van establir un Full de Ruta 2015-2017 amb projectes municipals i ciutadans per aconseguir aquests objectius. A partir de l’experiència d’aquests dos anys l’Ajuntament vol donar una resposta més potent i estructurada a aquest compromís i per això es proposa aglutinar les accions que du a terme al voltant del repte del canvi climàtic en un únic pla que integri totes les línies de treball: el Pla Clima.

És un pla que alhora concreta els compromisos internacionals signats per l’Ajuntament, com és el Pacte d’Alcaldes i Alcaldesses pel Clima i l’Energia Sostenible.

Qualitat de l’aire de la ciutat de Barcelona

Es mostren dades dels contaminants mesurats a les estacions de la ciutat de Barcelona. L’actualització es realitza en intervals d’una hora indicant si el valor està o no validat i també es mostren les dades dels tres dies anteriors a l’actual. Tanmateix es publiquen històrics amb periodicitat mensual.

library(tidyverse)
── Attaching packages ──────────────────────────────────────── tidyverse 1.2.1 ──
✔ ggplot2 3.1.0     ✔ readr   1.3.1
✔ tibble  2.1.3     ✔ purrr   0.3.1
✔ tidyr   0.8.3     ✔ stringr 1.4.0
✔ ggplot2 3.1.0     ✔ forcats 0.3.0
── Conflicts ─────────────────────────────────────────── tidyverse_conflicts() ──
✖ lubridate::as.difftime() masks base::as.difftime()
✖ dplyr::between()         masks data.table::between()
✖ lubridate::date()        masks base::date()
✖ dplyr::filter()          masks stats::filter()
✖ dplyr::first()           masks data.table::first()
✖ lubridate::hour()        masks data.table::hour()
✖ lubridate::intersect()   masks base::intersect()
✖ lubridate::isoweek()     masks data.table::isoweek()
✖ dplyr::lag()             masks stats::lag()
✖ dplyr::last()            masks data.table::last()
✖ lubridate::mday()        masks data.table::mday()
✖ lubridate::minute()      masks data.table::minute()
✖ lubridate::month()       masks data.table::month()
✖ lubridate::quarter()     masks data.table::quarter()
✖ lubridate::second()      masks data.table::second()
✖ lubridate::setdiff()     masks base::setdiff()
✖ purrr::transpose()       masks data.table::transpose()
✖ lubridate::union()       masks base::union()
✖ lubridate::wday()        masks data.table::wday()
✖ lubridate::week()        masks data.table::week()
✖ lubridate::yday()        masks data.table::yday()
✖ lubridate::year()        masks data.table::year()
library(data.table) 
library(dplyr)
library(lubridate)

rr gener <- tbl_df(fread(/2019_01_Gener_qualitat_aire_BCN.csv, header=TRUE)) gener %>% select(nom_cabina, longitud, latitud) %>% distinct()

rr gener2 <- gener %>% mutate(sector = as.factor(str_extract(nom_cabina, \(?<=[-]\\D).*\)), qualitat_aire = as.factor(qualitat_aire), qualitat_o3 = as.factor(qualitat_o3), valor_o3 = as.numeric(str_extract(valor_o3, ^[[:digit:]])), qualitat_no2 = as.factor(qualitat_no2), valor_no2 = as.numeric(str_extract(valor_no2, ^[[:digit:]])), qualitat_pm10 = as.factor(qualitat_pm10), valor_pm10 = as.numeric(str_extract(valor_pm10, ^[[:digit:]])), generat = dmy_hm(generat) ) %>% select(sector, qualitat_aire, qualitat_o3, valor_o3, qualitat_no2, valor_no2, qualitat_pm10, valor_pm10, generat) summary(gener2)

          sector     qualitat_aire  qualitat_o3     valor_o3      qualitat_no2 
 Ciutadella  : 738   --     : 162   --   : 287   Min.   :1.000   --     : 341  
 Eixample    : 738   Bona   :5571   Bona :4035   1st Qu.:2.000   Bona   :5358  
 Gràcia      : 738   Pobra  :   6   Pobra:   1   Median :4.000   Regular:  75  
 Observ Fabra: 738   Regular: 165   NA's :1581   Mean   :3.714   NA's   : 130  
 Palau Reial : 738                               3rd Qu.:5.000                 
 Poblenou    : 738                               Max.   :9.000                 
 (Other)     :1476                               NA's   :1868                  
   valor_no2     qualitat_pm10    valor_pm10       generat                   
 Min.   :1.000   --     :  42   Min.   :1.000   Min.   :2019-01-01 00:00:00  
 1st Qu.:2.000   Bona   :4238   1st Qu.:1.000   1st Qu.:2019-01-08 17:00:00  
 Median :3.000   Pobra  :   5   Median :1.000   Median :2019-01-16 14:30:00  
 Mean   :3.654   Regular: 102   Mean   :2.447   Mean   :2019-01-16 12:34:13  
 3rd Qu.:5.000   NA's   :1517   3rd Qu.:2.000   3rd Qu.:2019-01-24 07:00:00  
 Max.   :9.000                  Max.   :9.000   Max.   :2019-01-31 23:00:00  
 NA's   :471                    NA's   :1559                                 

rr gener2 %>% filter(sector == Reial) %>% select(valor_no2, generat) %>% ggplot(aes(x = generat, y = valor_no2)) + geom_line()

rr gener2 %>% filter(sector == Reial, generat >= as.Date(019-01-15), generat <= as.Date(019-01-16)) %>% select(valor_no2, generat) %>% ggplot(aes(x = generat, y = valor_no2)) + geom_line() + geom_point()

rr NA

rr gener3 <- gener %>% mutate(sector = as.factor(str_extract(nom_cabina, \(?<=[-]\\D).*\)), qualitat_aire = as.factor(qualitat_aire), qualitat_o3 = as.factor(qualitat_o3), valor_o3 = as.numeric(str_extract(valor_o3, ^[[:digit:]])), qualitat_no2 = as.factor(qualitat_no2), valor_no2 = as.numeric(str_extract(valor_no2, ^[[:digit:]])), qualitat_pm10 = as.factor(qualitat_pm10), valor_pm10 = as.numeric(str_extract(valor_pm10, ^[[:digit:]])), date = str_extract(generat, .*[[:space:]]), hour = str_extract(generat, \(?<=[[:space:]])[0-9.]+\)) %>% separate(col = date, into = c(, , ), sep = /) %>% mutate(day = as.integer(day), month = as.integer(month), year = as.integer(year), hour = as.integer(hour)) %>% select(sector, qualitat_aire, qualitat_o3, valor_o3, qualitat_no2, valor_no2, qualitat_pm10, valor_pm10, day, month, year, hour) summary(gener3)

          sector     qualitat_aire  qualitat_o3     valor_o3      qualitat_no2 
 Ciutadella  : 738   --     : 162   --   : 287   Min.   :1.000   --     : 341  
 Eixample    : 738   Bona   :5571   Bona :4035   1st Qu.:2.000   Bona   :5358  
 Gràcia      : 738   Pobra  :   6   Pobra:   1   Median :4.000   Regular:  75  
 Observ Fabra: 738   Regular: 165   NA's :1581   Mean   :3.714   NA's   : 130  
 Palau Reial : 738                               3rd Qu.:5.000                 
 Poblenou    : 738                               Max.   :9.000                 
 (Other)     :1476                               NA's   :1868                  
   valor_no2     qualitat_pm10    valor_pm10         day            month  
 Min.   :1.000   --     :  42   Min.   :1.000   Min.   : 1.00   Min.   :1  
 1st Qu.:2.000   Bona   :4238   1st Qu.:1.000   1st Qu.: 8.00   1st Qu.:1  
 Median :3.000   Pobra  :   5   Median :1.000   Median :16.00   Median :1  
 Mean   :3.654   Regular: 102   Mean   :2.447   Mean   :16.05   Mean   :1  
 3rd Qu.:5.000   NA's   :1517   3rd Qu.:2.000   3rd Qu.:24.00   3rd Qu.:1  
 Max.   :9.000                  Max.   :9.000   Max.   :31.00   Max.   :1  
 NA's   :471                    NA's   :1559                               
      year           hour      
 Min.   :2019   Min.   : 0.00  
 1st Qu.:2019   1st Qu.: 5.00  
 Median :2019   Median :11.00  
 Mean   :2019   Mean   :11.43  
 3rd Qu.:2019   3rd Qu.:17.00  
 Max.   :2019   Max.   :23.00  
                               

BV: µg/m³ medio de contaminadores por horas en enero en 8 barrios de Barcelona.

rr gener3 %>% gather(measure, measure_value, valor_o3, valor_no2, valor_pm10) %>% filter(year == 2019, month == 1) %>% select(day, hour, measure, measure_value, sector) %>% group_by(hour, measure, sector) %>% summarise(mean_val_hour = mean(measure_value, na.rm = TRUE)) %>% ggplot(aes(hour, mean_val_hour, color = measure)) + labs(title = /m³ medio de contaminadores, x = , y = /m³ medio, color = , caption = de opendata-ajuntament.barcelona.cat) + scale_color_discrete(labels = c(2, 3, 10)) + geom_line() + geom_point() + facet_wrap(~ sector, nrow = 2) + theme_minimal()

The study suggested that for 2015, the total existing UK vegetation reduces the average annual surface concentration by about 10% for PM2.5, 6% for PM10, 13% for O3, 24% for NH3 and 30% for SO2, but did not markedly change NO2 concentrations. https://airqualitynews.com/2018/07/30/plants-and-trees-not-the-solution-to-air-pollution-in-cities/

Cleaning dataset function:

clean_bcn_data <- function(data) {
  data <- data %>% 
  mutate(sector = as.factor(str_extract(nom_cabina, "(?<=[-]\\D).*")),
         qualitat_aire = as.factor(qualitat_aire),
         qualitat_o3 = as.factor(qualitat_o3),
         valor_o3 = as.numeric(str_extract(valor_o3, "^[[:digit:]]")),
         qualitat_no2 = as.factor(qualitat_no2),
         valor_no2 = as.numeric(str_extract(valor_no2, "^[[:digit:]]")),
         qualitat_pm10 = as.factor(qualitat_pm10),
         valor_pm10 = as.numeric(str_extract(valor_pm10, "^[[:digit:]]")),
         date = str_extract(generat, ".*[[:space:]]"),
         hour = str_extract(generat, "(?<=[[:space:]])[0-9.]+")) %>%
  separate(col = date, into = c("day", "month", "year"), sep = "/") %>%
  mutate(day = as.integer(day),
         month = as.integer(month),
         year = as.integer(year),
         hour = as.integer(hour),
         #sector = case_when(sector == "Ciutadella" ~ as.factor("Ciutat Vella"), TRUE ~ as.factor(sector)),
         month = case_when(month == 1 ~ as.integer(13), TRUE ~ as.integer(month))) %>%
  select(sector, qualitat_aire, qualitat_o3, valor_o3, qualitat_no2, valor_no2, qualitat_pm10,
         valor_pm10, day, month, year, hour)
  data
}

Aggregate data:

data_06_2018 <- tbl_df(fread("data/2018_06_Juny_qualitat_aire_BCN.csv", header=TRUE))
data_07_2018 <- tbl_df(fread("data/2018_07_Juliol_qualitat_aire_BCN.csv", header=TRUE))
data_08_2018 <- tbl_df(fread("data/2018_08_Agost_qualitat_aire_BCN.csv", header=TRUE))
data_09_2018 <- tbl_df(fread("data/2018_09_Setembre_qualitat_aire_BCN.csv", header=TRUE))
data_10_2018 <- tbl_df(fread("data/2018_10_Octubre_qualitat_aire_BCN.csv", header=TRUE))
data_12_2018 <- tbl_df(fread("data/2018_12_Desembre_qualitat_aire_BCN.csv", header=TRUE))
data_11_2018 <- tbl_df(fread("data/2018_11_novembre_qualitat_aire_BCN.csv", header=TRUE))
data_01_2019 <- tbl_df(fread("data/2019_01_Gener_qualitat_aire_BCN.csv", header=TRUE))
data <- rbind(data_06_2018,
              data_07_2018,
              data_08_2018,
              data_09_2018,
              data_10_2018,
              data_11_2018,
              data_12_2018,
              data_01_2019) %>% clean_bcn_data() 
summary(data)
         sector     qualitat_aire    qualitat_o3       valor_o3    
 Ciutadella :5320   --     : 2573   --     : 1893   Min.   :1.000  
 Eixample   :5320   Bona   :36760   Bona   :27028   1st Qu.:2.000  
 Gràcia     :5320   Pobra  :  160   Pobra  :   18   Median :4.000  
 Palau Reial:5320   Regular: 2394   Regular:  541   Mean   :4.196  
 Poblenou   :5320                   NA's   :12407   3rd Qu.:6.000  
 Sants      :5320                                   Max.   :9.000  
 (Other)    :9967                                   NA's   :14309  
  qualitat_no2     valor_no2     qualitat_pm10     valor_pm10         day       
 --     : 2302   Min.   :1.000   --     :  542   Min.   :1.000   Min.   : 1.00  
 Bona   :36990   1st Qu.:2.000   Bona   :23621   1st Qu.:1.000   1st Qu.: 9.00  
 Regular:  595   Median :3.000   Pobra  :  142   Median :2.000   Median :16.00  
 NA's   : 2000   Mean   :3.548   Regular: 1393   Mean   :2.316   Mean   :16.34  
                 3rd Qu.:5.000   NA's   :16189   3rd Qu.:3.000   3rd Qu.:24.00  
                 Max.   :9.000                   Max.   :9.000   Max.   :31.00  
                 NA's   :4311                    NA's   :16740                  
     month             year           hour     
 Min.   : 6.000   Min.   :2018   Min.   : 0.0  
 1st Qu.: 8.000   1st Qu.:2018   1st Qu.: 6.0  
 Median :10.000   Median :2018   Median :12.0  
 Mean   : 9.847   Mean   :2018   Mean   :11.6  
 3rd Qu.:12.000   3rd Qu.:2018   3rd Qu.:18.0  
 Max.   :13.000   Max.   :2019   Max.   :23.0  
                                               
plotit <- data %>% 
  gather(measure, measure_value, valor_o3, valor_no2, valor_pm10) %>%
  filter(year >= 2018, month >= 6, sector %in% c("Eixample", "Palau Reial", "Vall Hebron")) %>%
  select(month, day, hour, measure, measure_value, sector) %>%
  group_by(month, hour, measure, sector) %>%
  summarise(mean_val_hour = mean(measure_value, na.rm = TRUE)) %>%
  ggplot(aes(hour, mean_val_hour, color = measure)) +
  labs(title = "µg/m³ medio de contaminadores",
       x = "Hora", 
       y = "µg/m³ medio",
       color = "Contaminador",
       caption = "Datos de opendata-ajuntament.barcelona.cat") +
  scale_color_discrete(labels = c("NO2", "O3", "PM10")) +
  geom_line() +
  geom_point() + 
  facet_grid(sector ~ month) +
  theme_minimal()
(j <- data %>% 
  gather(measure, measure_value, valor_o3, valor_no2, valor_pm10) %>%
  #filter(year >= 2018, month >= 6, sector %in% c("Eixample", "Palau Reial", "Vall Hebron")) %>%
  filter(year >= 2018, month >= 6) %>%
  select(month, day, hour, measure, measure_value, sector) %>%
   mutate(measure = case_when(measure == "valor_no2" ~ "NO2",
                              measure == "valor_o3" ~ "O3",
                              measure == "valor_pm10" ~ "PM10",
                              TRUE ~ measure)) %>%
  group_by(month, measure, sector) %>%
  summarise(mean_val_month = mean(measure_value, na.rm = TRUE)) %>%
  ggplot(aes(month, mean_val_month)) +
  labs(title = "Monthly average of pollutants colored by district, June 2018 - Jan 2019",
       x = "Month", 
       y = "µg/m³",
       color = "District",
       caption = "Data from opendata-ajuntament.barcelona.cat") +
  #scale_color_discrete(labels = c("NO2", "O3", "PM10")) +
  geom_line(size=1, aes(color = sector)) +
  geom_smooth(se=FALSE, color="black", linetype = "dashed", method=lm) +
  #geom_point() + 
  facet_wrap(~ measure, ncol = 3) +
  theme_mine())

#method=lm for geom_smooth
ggplotly(j) 
Removed 36 rows containing non-finite values (stat_smooth).
saveWidget(ggplotly(j, dynamicTicks = TRUE), file = "meanbymonth2018.html")
Removed 36 rows containing non-finite values (stat_smooth).
data %>% 
  gather(measure, measure_value, valor_o3, valor_no2, valor_pm10) %>%
  #filter(year >= 2018, month >= 6, sector %in% c("Eixample", "Palau Reial", "Vall Hebron")) %>%
  filter(year >= 2018, month >= 6) %>%
  select(month, day, hour, measure, measure_value, sector) %>%
  group_by(month, measure, sector) %>%
  summarise(mean_val_month = mean(measure_value, na.rm = TRUE)) %>%
  ggplot(aes(month, mean_val_month, color = measure)) +
  labs(title = "µg/m³ medio de contaminadores",
       x = "Mes", 
       y = "µg/m³ medio",
       color = "Contaminador",
       caption = "Datos de opendata-ajuntament.barcelona.cat") +
  scale_color_discrete(labels = c("NO2", "O3", "PM10")) +
  geom_line(size=1) +
  #geom_point() + 
  facet_wrap(~ sector, ncol = 4) +
  theme_mine()

(plotit <- data %>% 
  gather(measure, measure_value, valor_o3, valor_no2, valor_pm10) %>%
  filter(year >= 2018, month >= 6, sector %in% c("Eixample", "Palau Reial", "Vall Hebron")) %>%
  select(month, day, hour, measure, measure_value, sector) %>%
  group_by(month, sector) %>%
  summarise(mean_val_month = mean(measure_value, na.rm = TRUE)) %>%
  ggplot(aes(month, mean_val_month)) +
  labs(title = "µg/m³ medio de contaminadores",
       x = "Mes", 
       y = "µg/m³ medio",
       caption = "Datos de opendata-ajuntament.barcelona.cat") +
  geom_line() +
  geom_point() + 
  facet_wrap(~ sector, nrow = 4) +
  theme_mine())

library(plotly)

Attaching package: ‘plotly’

The following object is masked from ‘package:ggplot2’:

    last_plot

The following object is masked from ‘package:stats’:

    filter

The following object is masked from ‘package:graphics’:

    layout
library(htmlwidgets)

Just clean

clean_data <- function(data) {
  data <- data %>% 
  mutate(sector = as.factor(str_extract(nom_cabina, "(?<=[-]\\D).*")),
         qualitat_aire = as.factor(qualitat_aire),
         qualitat_o3 = as.factor(qualitat_o3),
         valor_o3 = as.numeric(str_extract(valor_o3, "^[[:digit:]]")),
         qualitat_no2 = as.factor(qualitat_no2),
         valor_no2 = as.numeric(str_extract(valor_no2, "^[[:digit:]]")),
         qualitat_pm10 = as.factor(qualitat_pm10),
         valor_pm10 = as.numeric(str_extract(valor_pm10, "^[[:digit:]]")),
         date = str_extract(generat, ".*[[:space:]]"),
         hour = str_extract(generat, "(?<=[[:space:]])[0-9.]+")) %>%
  separate(col = date, into = c("day", "month", "year"), sep = "/") %>%
  mutate(day = as.integer(day),
         month = as.integer(month),
         year = as.integer(year),
         hour = as.integer(hour),
         month = as.integer(month)) %>%
  select(sector, qualitat_aire, qualitat_o3, valor_o3, qualitat_no2, valor_no2, qualitat_pm10,
         valor_pm10, day, month, year, hour)
  data
}
(p <- data_06_2018 %>% clean_data() %>%
  gather(measure, measure_value, valor_o3, valor_no2, valor_pm10) %>%
  filter(year == 2018, month == 6) %>%
  select(day, hour, measure, measure_value, sector) %>%
   mutate(measure = case_when(measure == "valor_no2" ~ "NO2",
                              measure == "valor_o3" ~ "O3",
                              measure == "valor_pm10" ~ "PM10",
                              TRUE ~ measure)) %>%
  group_by(hour, measure, sector) %>%
  summarise(mean_val_hour = mean(measure_value, na.rm = TRUE)) %>%
   
   
   
  ggplot(aes(hour, mean_val_hour, color = measure)) +
  labs(title = "Mean value of pollutants by hour in June 2018",
       x = "Hour", 
       y = "µg/m³",
       color = "Pollutant",
       caption = "Data from opendata-ajuntament.barcelona.cat") +
  #scale_color_discrete(labels = c("NO2", "O3", "PM10")) +
  geom_line(size=1) +
  #geom_point() + 
  facet_wrap(~ sector, nrow = 2) +
  theme_mine()
  )

saveWidget(ggplotly(p, dynamicTicks = TRUE), file = "meanjun.html")
ggplotly(p) 

Mortalitat

mortalitat <- tbl_df(fread("2018_taxa_mortalitat.csv", header=TRUE))
Error in fread("2018_taxa_mortalitat.csv", header = TRUE) : 
  File '2018_taxa_mortalitat.csv' does not exist or is non-readable. getwd()=='/Users/3omni/Documents/GitHub/bcn-contamination-dataviz'
theme_mine <- function () { 
    theme_bw(base_size=12, base_family="Montserrat") %+replace% 
        theme(
            panel.background  = element_blank(),
            plot.background = element_rect(fill="#ebfff5", colour=NA), 
            legend.background = element_rect(fill="transparent", colour=NA),
            legend.key = element_rect(fill="transparent", colour=NA)
        )
}
data_06_2019 <- tbl_df(fread("data/2019_06_juny_qualitat_aire_BCN.csv", header=TRUE))
data_04_2019 <- tbl_df(fread("data/2019_04_Abril_qualitat_aire_BCN.csv", header=TRUE))
#summary(data_06_2019)
length(names(data_04_2019))
[1] 57
(i <- data_04_2019 %>%
  select(5:57) %>%
  mutate(measure = as.factor(case_when(CODI_CONTAMINANT == 1 ~ "SO2",
                              CODI_CONTAMINANT == 7 ~ "NO",
                              CODI_CONTAMINANT == 8 ~ "NO2",
                              CODI_CONTAMINANT == 12 ~ "NOx",
                              CODI_CONTAMINANT == 14 ~ "O3",
                              CODI_CONTAMINANT == 6 ~ "CO",
                              CODI_CONTAMINANT == 10 ~ "PM10",
                              TRUE ~ ""))) %>%
  mutate(sector = as.factor(case_when(ESTACIO == 4 ~ "Poblenou",
                              ESTACIO == 42 ~ "Sants",
                              ESTACIO == 43 ~ "Eixample",
                              ESTACIO == 44 ~ "Gràcia",
                              ESTACIO == 50 ~ "Ciutadella",
                              ESTACIO == 54 ~ "Vall Hebron",
                              ESTACIO == 57 ~ "Palau Reial",
                              TRUE ~ ""))) %>%
  gather(hour, measure_value, starts_with("H")) %>%
  gather(validation, val, starts_with("V")) %>% distinct() %>%
  mutate(day = as.integer(DIA),
         month = as.integer(MES),
         year = as.integer(ANY),
         hour = as.integer(str_extract(hour,"..$"))) %>%
  select(sector, year, month, day, hour, measure, measure_value) %>%
  #filter(sector == "Ciutadella") %>%
  group_by(hour, measure, sector) %>%
  summarise(mean_val_hour = mean(measure_value, na.rm = TRUE)) %>%
    
  ggplot(aes(hour, mean_val_hour, color = measure)) +
  labs(title = "Mean value of pollutants by hour in April 2019",
       x = "Hour", 
       y = "µg/m³",
       color = "Pollutant",
       caption = "Data from opendata-ajuntament.barcelona.cat") +
  #scale_color_discrete(labels = c("NO2", "O3", "PM10")) +
  #scale_color_manual(values = c("purple", "yellow", "red", "orange", "green", "blue", "pink")) +
  geom_line(size=1) +
  #geom_hline(yintercept = 90, linetype = 2, color = "red") +
  #geom_hline(yintercept = 110, linetype = 2, color = "green") +
  #geom_hline(yintercept = 200, linetype = 2, color = "pink") +
  #geom_text(aes(0,90,label = "Limit NO2 by h", vjust = -1), color = "black") +
  #geom_point() + 
  scale_x_continuous(limits = c(0, 22)) + 
  facet_wrap(~ sector, nrow = 1) +
  theme_mine())

NA
ggplotly(i) 
saveWidget(ggplotly(i, dynamicTicks = TRUE), file = "meanapr19.html")
april19 <- data_04_2019 %>%
  select(5:57) %>%
  mutate(measure = as.factor(case_when(CODI_CONTAMINANT == 1 ~ "SO2",
                              CODI_CONTAMINANT == 7 ~ "NO",
                              CODI_CONTAMINANT == 8 ~ "NO2",
                              CODI_CONTAMINANT == 12 ~ "NOx",
                              CODI_CONTAMINANT == 14 ~ "O3",
                              CODI_CONTAMINANT == 6 ~ "CO",
                              CODI_CONTAMINANT == 10 ~ "PM10",
                              TRUE ~ ""))) %>%
  mutate(sector = as.factor(case_when(ESTACIO == 4 ~ "Poblenou",
                              ESTACIO == 42 ~ "Sants",
                              ESTACIO == 43 ~ "Eixample",
                              ESTACIO == 44 ~ "Gràcia",
                              ESTACIO == 50 ~ "Ciutadella",
                              ESTACIO == 54 ~ "Vall Hebron",
                              ESTACIO == 57 ~ "Palau Reial",
                              TRUE ~ ""))) %>%
  gather(hour, measure_value, starts_with("H")) %>%
  gather(validation, val, starts_with("V")) %>% distinct() %>%
  mutate(day = as.integer(DIA),
         month = as.integer(MES),
         year = as.integer(ANY),
         hour = as.integer(str_extract(hour,"..$"))) %>%
  select(sector, year, month, day, hour, measure, measure_value)
june19 <- data_06_2019 %>%
  select(5:57) %>%
  mutate(measure = as.factor(case_when(CODI_CONTAMINANT == 1 ~ "SO2",
                              CODI_CONTAMINANT == 7 ~ "NO",
                              CODI_CONTAMINANT == 8 ~ "NO2",
                              CODI_CONTAMINANT == 12 ~ "NOx",
                              CODI_CONTAMINANT == 14 ~ "O3",
                              CODI_CONTAMINANT == 6 ~ "CO",
                              CODI_CONTAMINANT == 10 ~ "PM10",
                              TRUE ~ ""))) %>%
  mutate(sector = as.factor(case_when(ESTACIO == 4 ~ "Poblenou",
                              ESTACIO == 42 ~ "Sants",
                              ESTACIO == 43 ~ "Eixample",
                              ESTACIO == 44 ~ "Gràcia",
                              ESTACIO == 50 ~ "Ciutadella",
                              ESTACIO == 54 ~ "Vall Hebron",
                              ESTACIO == 57 ~ "Palau Reial",
                              TRUE ~ ""))) %>%
  gather(hour, measure_value, starts_with("H")) %>%
  gather(validation, val, starts_with("V")) %>% distinct() %>%
  mutate(day = as.integer(DIA),
         month = as.integer(MES),
         year = as.integer(ANY),
         hour = as.integer(str_extract(hour,"..$"))) %>%
  select(sector, year, month, day, hour, measure, measure_value)
data19 <- rbind(april19, june19)
summary(data19)
         sector            year          month            day             hour      
 Ciutadella :135936   Min.   :2019   Min.   :4.000   Min.   : 1.00   Min.   : 1.00  
 Eixample   :237888   1st Qu.:2019   1st Qu.:4.000   1st Qu.: 8.00   1st Qu.: 6.75  
 Gràcia     :237888   Median :2019   Median :6.000   Median :16.00   Median :12.50  
 Palau Reial:237888   Mean   :2019   Mean   :5.014   Mean   :15.75   Mean   :12.50  
 Poblenou   :132480   3rd Qu.:2019   3rd Qu.:6.000   3rd Qu.:23.00   3rd Qu.:18.25  
 Sants      :101952   Max.   :2019   Max.   :6.000   Max.   :30.00   Max.   :24.00  
 Vall Hebron:237888                                                                 
 measure       measure_value   
 CO  :135936   Min.   :  0.20  
 NO  :237888   1st Qu.:  2.00  
 NO2 :237888   Median : 17.00  
 NOx :237888   Mean   : 27.36  
 O3  :169920   3rd Qu.: 41.00  
 PM10:166464   Max.   :759.00  
 SO2 :135936   NA's   :44856   
(k <- data19 %>% 
  filter(year >= 2019, month >= 4) %>%
  group_by(month, measure, sector) %>%
  summarise(mean_val_month = mean(measure_value, na.rm = TRUE)) %>%
  #select(month, day, hour, measure, measure_value, sector) %>%
  ggplot(aes(month, mean_val_month)) +
  labs(title = "Monthly average of pollutants colored by district, April 2019 - June 2019",
       x = "Month", 
       y = "µg/m³",
       color = "District",
       caption = "Data from opendata-ajuntament.barcelona.cat") +
  #scale_color_discrete(labels = c("NO2", "O3", "PM10")) +
  geom_line(size=1, aes(color = sector)) +
  #geom_smooth(se=FALSE, color="black", linetype = "dashed", method=lm) +
  #geom_point() + 
  scale_x_continuous(breaks = c(4,6)) +
  facet_wrap(~ measure, ncol = 7) +
  theme_mine())

#method=lm for geom_smooth
ggplotly(k) 
saveWidget(ggplotly(k, dynamicTicks = TRUE), file = "mean19.html")
accidents18 <- tbl_df(fread("data/2018_accidents_causes_gu_bcn.csv",header=TRUE))
summary(accidents18)
 Numero_expedient   Codi_districte   Nom_districte        Codi_barri  Nom_barri        
 Length:9926        Min.   :-1.000   Length:9926        Min.   :-1   Length:9926       
 Class :character   1st Qu.: 2.000   Class :character   1st Qu.: 8   Class :character  
 Mode  :character   Median : 4.000   Mode  :character   Median :20   Mode  :character  
                    Mean   : 4.834                      Mean   :27                     
                    3rd Qu.: 7.000                      3rd Qu.:43                     
                    Max.   :10.000                      Max.   :73                     
  Codi_carrer      Nom_carrer         Num_postal        Descripcio_dia_setmana
 Min.   :    -1   Length:9926        Length:9926        Length:9926           
 1st Qu.:119003   Class :character   Class :character   Class :character      
 Median :191204   Mode  :character   Mode  :character   Mode  :character      
 Mean   :250401                                                               
 3rd Qu.:320908                                                               
 Max.   :701857                                                               
 Dia_setmana        Descripcio_tipus_dia      Any          Mes_any         Nom_mes         
 Length:9926        Length:9926          Min.   :2018   Min.   : 1.000   Length:9926       
 Class :character   Class :character     1st Qu.:2018   1st Qu.: 4.000   Class :character  
 Mode  :character   Mode  :character     Median :2018   Median : 6.000   Mode  :character  
                                         Mean   :2018   Mean   : 6.484                     
                                         3rd Qu.:2018   3rd Qu.:10.000                     
                                         Max.   :2018   Max.   :12.000                     
    Dia_mes         Hora_dia     Descripcio_torn    Descripcio_causa_mediata Coordenada_UTM_X
 Min.   : 1.00   Min.   : 0.00   Length:9926        Length:9926              Min.   :424027  
 1st Qu.: 8.00   1st Qu.:10.00   Class :character   Class :character         1st Qu.:428659  
 Median :16.00   Median :14.00   Mode  :character   Mode  :character         Median :430202  
 Mean   :15.66   Mean   :13.83                                               Mean   :430124  
 3rd Qu.:23.00   3rd Qu.:18.00                                               3rd Qu.:431564  
 Max.   :31.00   Max.   :23.00                                               Max.   :435086  
 Coordenada_UTM_Y     Longitud           Latitud        
 Min.   :4575229   Min.   :   2.090   Min.   :   41.32  
 1st Qu.:4582171   1st Qu.:   2.146   1st Qu.:   41.39  
 Median :4583422   Median :   2.164   Median :   41.40  
 Mean   :4583697   Mean   :   3.685   Mean   :   87.22  
 3rd Qu.:4584969   3rd Qu.:   2.180   3rd Qu.:   41.41  
 Max.   :4590759   Max.   :2188.000   Max.   :41414.00  
head(accidents18)
(ac<- accidents18 %>% filter(Mes_any >= 6, Any == 2018) %>%
  mutate(sector = case_when(Nom_districte == "Desconegut" ~ as.character(NA),TRUE ~ as.character(Nom_districte)),
         sector = as.factor(sector),
         year = Any,
         month = Mes_any,
         day = Dia_mes,
         hour = Hora_dia) %>%
   drop_na() %>%
  select(sector, year, month, day, hour))
levels(ac$sector)
 [1] "Ciutat Vella"        "Eixample"            "Gràcia"              "Horta-Guinardó"     
 [5] "Les Corts"           "Nou Barris"          "Sant Andreu"         "Sant Martí"         
 [9] "Sants-Montjuïc"      "Sarrià-Sant Gervasi"
ac %>%
  group_by(sector, month, hour) %>%
  summarize(incidents = n()) %>%
  ggplot(aes(x = hour, y = incidents, color = factor(month))) +
  geom_line() +
  geom_smooth(se = FALSE, size = 1, color = "black") +
  #geom_point() + 
  facet_wrap(~ sector, ncol = 5) +
  theme_minimal()

NA
ac %>%
  group_by(sector, hour) %>%
  summarize(incidents = n()) %>%
  ggplot(aes(x = hour, y = incidents, color = sector)) +
  geom_line() +
  geom_smooth(se = FALSE, size = 1, color = "black") +
  #geom_point() + 
  #facet_wrap(~ sector, ncol = 5) +
  theme_minimal()

NA
ac %>%
  group_by(sector, month) %>%
  summarize(incidents = n()) %>%
  ggplot(aes(x = month, y = incidents, color = sector)) +
  geom_line() +
  geom_smooth(se = FALSE, size = 1, color = "black") +
  #geom_point() + 
  #facet_wrap(~ sector, ncol = 5) +
  theme_minimal()

NA
LS0tCnRpdGxlOiAiT3BlbiBEYXRhIEJhcmNlbG9uYSIKYXV0aG9yOiAiUml0YSIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQojIyMgUGxhIENsaW1hCgpFbCBjYW52aSBjbGltw6B0aWMgw6lzIHVuYSByZWFsaXRhdCBpIGVzdMOgIG9jYXNpb25hdCBwZXIgbOKAmcOpc3NlciBodW3DoC4gSmEgdGVuaW0gZXZpZMOobmNpZXMgZGVscyBzZXVzIGltcGFjdGVzIGkgY2FsIGFjdHVhciBwZXIgYSBmZXItaGkgZnJvbnQuICAKCkxlcyBjaXV0YXRzIHPDs24gZXNwZWNpYWxtZW50IHZ1bG5lcmFibGVzLCBqYSBxdWUgY29uY2VudHJlbiBsYSBtYWpvcmlhIGRlIGxhIHBvYmxhY2nDsyBtdW5kaWFsIGkgw6lzIG9uIGzigJllbmVyZ2lhIGVzIGNvbnN1bWVpeCBkZSBtYW5lcmEgbcOpcyBpbnRlbnNpdmEsIGdlbmVyYW50IGVsIDcwJSBkZSBsZXMgZW1pc3Npb25zIGRlIGdhc29zIGFtYiBlZmVjdGUgZOKAmWhpdmVybmFjbGUuCgpCYXJjZWxvbmEgw6lzIHVuYSBjaXV0YXQgbWVkaXRlcnLDoG5pYSwgcXVlIGNvbnN1bWVpeCBwb2NhIGVuZXJnaWEgaSBnZW5lcmEgcG9xdWVzIGVtaXNzaW9ucyBwZXIgY8OgcGl0YSBlbiByZWxhY2nDsyBhIGFsdHJlcyBjaXV0YXRzIHNpbWlsYXJzLCBwZXLDsiBlbmNhcmEgdMOpIG1vbHQgY2Ftw60gcGVyIHJlY8OzcnJlciwgamEgcXVlIHTDqSB1bmEgZWxldmFkYSBkZXBlbmTDqG5jaWEgZGUgcmVjdXJzb3MgZsOyc3NpbHMgaSBudWNsZWFycy4KCkVscyBlZmVjdGVzIGRlbCBjYW52aSBjbGltw6B0aWMgcG9kcmllbiBwcmVzZW50YXIgcmlzY29zIGVuIHRlcm1lcyBkZSBzYWx1dCBpIGJlbmVzdGFyIGRlIGxlcyBwZXJzb25lcyAob25hZGVzIGRlIGNhbG9yKSwgZGUgc2VndXJldGF0IChnYXJhbnRpYSBkZSBzdWJtaW5pc3RyYW1lbnQgZOKAmWFpZ3VhIGkgZOKAmWVuZXJnaWEsIHZ1bG5lcmFiaWxpdGF0IGRlIGxlcyBpbmZyYWVzdHJ1Y3R1cmVzLCByaXNjIGTigJlpbmNlbmRpcy4uKSBpIGVuIGzigJllbnRvcm4gbmF0dXJhbCBxdWUgY2FsIHByZXZldXJlIGkgcHJldmVuaXIgYSBuaXZlbGwgZ2xvYmFsLgoKQW1iIG1vdGl1IGRlIGxhIGNlbGVicmFjacOzIGEgUGFyw61zIGRlIGxhIENPUDIxLCBsYSAyMWEgQ29uZmVyw6huY2lhIGRlIGxlcyBQYXJ0cyBkZSBsYSBDb252ZW5jacOzIE1hcmMgZGUgbGVzIE5hY2lvbnMgVW5pZGVzIHNvYnJlIGVsIENhbnZpIENsaW3DoHRpYywgaSBlbiBlbCBtYXJjIGRlbCBDb21wcm9tw61zIENpdXRhZMOgIHBlciBsYSBTb3N0ZW5pYmlsaXRhdCwgQmFyY2Vsb25hIHZhIGNvbmNyZXRhciB1biBDb21wcm9tw61zIGRlIEJhcmNlbG9uYSBwZWwgQ2xpbWEsIGVuIHF1w6ggZXMgY29tcHJvbWV0aWEgYSByZWR1aXIgbGVzIGVtaXNzaW9ucyBkZSBnYXNvcyBlbSBlZmVjdGUgaGl2ZXJuYWNsZSB1biA0MCUgYWwgMjAzMCBlbiByZWxhY2nDsyBhbCAyMDA1IGkgYXVnbWVudGFyIDEsNmttMiBkZSB2ZXJkIHVyYsOgIGNvbSBhIG1lc3VyYSBk4oCZYWRhcHRhY2nDsy4KCkFqdW50YW1lbnQgaSBjaXV0YWRhbmlhIHZhbiBlc3RhYmxpciB1biBGdWxsIGRlIFJ1dGEgMjAxNS0yMDE3IGFtYiBwcm9qZWN0ZXMgbXVuaWNpcGFscyBpIGNpdXRhZGFucyBwZXIgYWNvbnNlZ3VpciBhcXVlc3RzIG9iamVjdGl1cy4gQSBwYXJ0aXIgZGUgbOKAmWV4cGVyacOobmNpYSBk4oCZYXF1ZXN0cyBkb3MgYW55cyBs4oCZQWp1bnRhbWVudCB2b2wgZG9uYXIgdW5hIHJlc3Bvc3RhIG3DqXMgcG90ZW50IGkgZXN0cnVjdHVyYWRhIGEgYXF1ZXN0IGNvbXByb23DrXMgaSBwZXIgYWl4w7IgZXMgcHJvcG9zYSBhZ2x1dGluYXIgbGVzIGFjY2lvbnMgcXVlIGR1IGEgdGVybWUgYWwgdm9sdGFudCBkZWwgcmVwdGUgZGVsIGNhbnZpIGNsaW3DoHRpYyBlbiB1biDDum5pYyBwbGEgcXVlIGludGVncmkgdG90ZXMgbGVzIGzDrW5pZXMgZGUgdHJlYmFsbDogZWwgUGxhIENsaW1hLgoKw4lzIHVuIHBsYSBxdWUgYWxob3JhIGNvbmNyZXRhIGVscyBjb21wcm9taXNvcyBpbnRlcm5hY2lvbmFscyBzaWduYXRzIHBlciBs4oCZQWp1bnRhbWVudCwgY29tIMOpcyBlbCBQYWN0ZSBk4oCZQWxjYWxkZXMgaSBBbGNhbGRlc3NlcyBwZWwgQ2xpbWEgaSBs4oCZRW5lcmdpYSBTb3N0ZW5pYmxlLgoKIyMgUXVhbGl0YXQgZGUgbCdhaXJlIGRlIGxhIGNpdXRhdCBkZSBCYXJjZWxvbmEKRXMgbW9zdHJlbiBkYWRlcyBkZWxzIGNvbnRhbWluYW50cyBtZXN1cmF0cyBhIGxlcyBlc3RhY2lvbnMgZGUgbGEgY2l1dGF0IGRlIEJhcmNlbG9uYS4KTCdhY3R1YWxpdHphY2nDsyBlcyByZWFsaXR6YSBlbiBpbnRlcnZhbHMgZCd1bmEgaG9yYSBpbmRpY2FudCBzaSBlbCB2YWxvciBlc3TDoCBvIG5vIHZhbGlkYXQgaSB0YW1iw6kgZXMgbW9zdHJlbiBsZXMgZGFkZXMgZGVscyB0cmVzIGRpZXMgYW50ZXJpb3JzIGEgbCdhY3R1YWwuIFRhbm1hdGVpeCBlcyBwdWJsaXF1ZW4gaGlzdMOycmljcyBhbWIgcGVyaW9kaWNpdGF0IG1lbnN1YWwuCgpgYGB7cn0KbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoZGF0YS50YWJsZSkgCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkobHVicmlkYXRlKQpgYGAKCmBgYHtyfQpnZW5lciA8LSB0YmxfZGYoZnJlYWQoImRhdGEvMjAxOV8wMV9HZW5lcl9xdWFsaXRhdF9haXJlX0JDTi5jc3YiLAogICAgICAgICAgICAgICBoZWFkZXI9VFJVRSkpCmdlbmVyICU+JSBzZWxlY3Qobm9tX2NhYmluYSwgbG9uZ2l0dWQsIGxhdGl0dWQpICU+JSBkaXN0aW5jdCgpCmBgYAoKYGBge3J9CmdlbmVyMiA8LSBnZW5lciAlPiUKICBtdXRhdGUoc2VjdG9yID0gYXMuZmFjdG9yKHN0cl9leHRyYWN0KG5vbV9jYWJpbmEsICIoPzw9Wy1dXFxEKS4qIikpLAogICAgICAgICBxdWFsaXRhdF9haXJlID0gYXMuZmFjdG9yKHF1YWxpdGF0X2FpcmUpLAogICAgICAgICBxdWFsaXRhdF9vMyA9IGFzLmZhY3RvcihxdWFsaXRhdF9vMyksCiAgICAgICAgIHZhbG9yX28zID0gYXMubnVtZXJpYyhzdHJfZXh0cmFjdCh2YWxvcl9vMywgIl5bWzpkaWdpdDpdXSIpKSwKICAgICAgICAgcXVhbGl0YXRfbm8yID0gYXMuZmFjdG9yKHF1YWxpdGF0X25vMiksCiAgICAgICAgIHZhbG9yX25vMiA9IGFzLm51bWVyaWMoc3RyX2V4dHJhY3QodmFsb3Jfbm8yLCAiXltbOmRpZ2l0Ol1dIikpLAogICAgICAgICBxdWFsaXRhdF9wbTEwID0gYXMuZmFjdG9yKHF1YWxpdGF0X3BtMTApLAogICAgICAgICB2YWxvcl9wbTEwID0gYXMubnVtZXJpYyhzdHJfZXh0cmFjdCh2YWxvcl9wbTEwLCAiXltbOmRpZ2l0Ol1dIikpLAogICAgICAgICBnZW5lcmF0ID0gZG15X2htKGdlbmVyYXQpCiAgICAgICAgICkgJT4lCiAgc2VsZWN0KHNlY3RvciwgcXVhbGl0YXRfYWlyZSwgcXVhbGl0YXRfbzMsIHZhbG9yX28zLCBxdWFsaXRhdF9ubzIsIHZhbG9yX25vMiwgcXVhbGl0YXRfcG0xMCwKICAgICAgICAgdmFsb3JfcG0xMCwgZ2VuZXJhdCkKc3VtbWFyeShnZW5lcjIpCmBgYAoKYGBge3J9CmdlbmVyMiAlPiUgCiAgZmlsdGVyKHNlY3RvciA9PSAiUGFsYXUgUmVpYWwiKSAlPiUgCiAgc2VsZWN0KHZhbG9yX25vMiwgZ2VuZXJhdCkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gZ2VuZXJhdCwgeSA9IHZhbG9yX25vMikpICsKICBnZW9tX2xpbmUoKQoKYGBgCgpgYGB7cn0KZ2VuZXIyICU+JSAKICBmaWx0ZXIoc2VjdG9yID09ICJQYWxhdSBSZWlhbCIsIGdlbmVyYXQgPj0gYXMuRGF0ZSgiMjAxOS0wMS0xNSIpLCBnZW5lcmF0IDw9IGFzLkRhdGUoIjIwMTktMDEtMTYiKSkgJT4lIAogIHNlbGVjdCh2YWxvcl9ubzIsIGdlbmVyYXQpICU+JQogIGdncGxvdChhZXMoeCA9IGdlbmVyYXQsIHkgPSB2YWxvcl9ubzIpKSArCiAgZ2VvbV9saW5lKCkgKyBnZW9tX3BvaW50KCkKICAKCmBgYAoKCmBgYHtyfQpnZW5lcjMgPC0gZ2VuZXIgJT4lIAogIG11dGF0ZShzZWN0b3IgPSBhcy5mYWN0b3Ioc3RyX2V4dHJhY3Qobm9tX2NhYmluYSwgIig/PD1bLV1cXEQpLioiKSksCiAgICAgICAgIHF1YWxpdGF0X2FpcmUgPSBhcy5mYWN0b3IocXVhbGl0YXRfYWlyZSksCiAgICAgICAgIHF1YWxpdGF0X28zID0gYXMuZmFjdG9yKHF1YWxpdGF0X28zKSwKICAgICAgICAgdmFsb3JfbzMgPSBhcy5udW1lcmljKHN0cl9leHRyYWN0KHZhbG9yX28zLCAiXltbOmRpZ2l0Ol1dIikpLAogICAgICAgICBxdWFsaXRhdF9ubzIgPSBhcy5mYWN0b3IocXVhbGl0YXRfbm8yKSwKICAgICAgICAgdmFsb3Jfbm8yID0gYXMubnVtZXJpYyhzdHJfZXh0cmFjdCh2YWxvcl9ubzIsICJeW1s6ZGlnaXQ6XV0iKSksCiAgICAgICAgIHF1YWxpdGF0X3BtMTAgPSBhcy5mYWN0b3IocXVhbGl0YXRfcG0xMCksCiAgICAgICAgIHZhbG9yX3BtMTAgPSBhcy5udW1lcmljKHN0cl9leHRyYWN0KHZhbG9yX3BtMTAsICJeW1s6ZGlnaXQ6XV0iKSksCiAgICAgICAgIGRhdGUgPSBzdHJfZXh0cmFjdChnZW5lcmF0LCAiLipbWzpzcGFjZTpdXSIpLAogICAgICAgICBob3VyID0gc3RyX2V4dHJhY3QoZ2VuZXJhdCwgIig/PD1bWzpzcGFjZTpdXSlbMC05Ll0rIikpICU+JQogIHNlcGFyYXRlKGNvbCA9IGRhdGUsIGludG8gPSBjKCJkYXkiLCAibW9udGgiLCAieWVhciIpLCBzZXAgPSAiLyIpICU+JQogIG11dGF0ZShkYXkgPSBhcy5pbnRlZ2VyKGRheSksCiAgICAgICAgIG1vbnRoID0gYXMuaW50ZWdlcihtb250aCksCiAgICAgICAgIHllYXIgPSBhcy5pbnRlZ2VyKHllYXIpLAogICAgICAgICBob3VyID0gYXMuaW50ZWdlcihob3VyKSkgJT4lCiAgc2VsZWN0KHNlY3RvciwgcXVhbGl0YXRfYWlyZSwgcXVhbGl0YXRfbzMsIHZhbG9yX28zLCBxdWFsaXRhdF9ubzIsIHZhbG9yX25vMiwgcXVhbGl0YXRfcG0xMCwKICAgICAgICAgdmFsb3JfcG0xMCwgZGF5LCBtb250aCwgeWVhciwgaG91cikKc3VtbWFyeShnZW5lcjMpCmBgYAoKQlY6IMK1Zy9twrMgbWVkaW8gZGUgY29udGFtaW5hZG9yZXMgcG9yIGhvcmFzIGVuIGVuZXJvIGVuIDggYmFycmlvcyBkZSBCYXJjZWxvbmEuCmBgYHtyfQpnZW5lcjMgJT4lIAogIGdhdGhlcihtZWFzdXJlLCBtZWFzdXJlX3ZhbHVlLCB2YWxvcl9vMywgdmFsb3Jfbm8yLCB2YWxvcl9wbTEwKSAlPiUKICBmaWx0ZXIoeWVhciA9PSAyMDE5LCBtb250aCA9PSAxKSAlPiUKICBzZWxlY3QoZGF5LCBob3VyLCBtZWFzdXJlLCBtZWFzdXJlX3ZhbHVlLCBzZWN0b3IpICU+JQogIGdyb3VwX2J5KGhvdXIsIG1lYXN1cmUsIHNlY3RvcikgJT4lCiAgc3VtbWFyaXNlKG1lYW5fdmFsX2hvdXIgPSBtZWFuKG1lYXN1cmVfdmFsdWUsIG5hLnJtID0gVFJVRSkpICU+JQogIGdncGxvdChhZXMoaG91ciwgbWVhbl92YWxfaG91ciwgY29sb3IgPSBtZWFzdXJlKSkgKwogIGxhYnModGl0bGUgPSAiwrVnL23CsyBtZWRpbyBkZSBjb250YW1pbmFkb3JlcyIsCiAgICAgICB4ID0gIkhvcmEiLCAKICAgICAgIHkgPSAiwrVnL23CsyBtZWRpbyIsCiAgICAgICBjb2xvciA9ICJDb250YW1pbmFkb3IiLAogICAgICAgY2FwdGlvbiA9ICJEYXRvcyBkZSBvcGVuZGF0YS1hanVudGFtZW50LmJhcmNlbG9uYS5jYXQiKSArCiAgc2NhbGVfY29sb3JfZGlzY3JldGUobGFiZWxzID0gYygiTk8yIiwgIk8zIiwgIlBNMTAiKSkgKwogIGdlb21fbGluZSgpICsKICAjZ2VvbV9wb2ludCgpICsgCiAgZmFjZXRfd3JhcCh+IHNlY3RvciwgbnJvdyA9IDIpICsKICB0aGVtZV9taW5pbWFsKCkKYGBgCgpUaGUgc3R1ZHkgc3VnZ2VzdGVkIHRoYXQgZm9yIDIwMTUsIHRoZSB0b3RhbCBleGlzdGluZyBVSyB2ZWdldGF0aW9uIHJlZHVjZXMgdGhlIGF2ZXJhZ2UgYW5udWFsIHN1cmZhY2UgY29uY2VudHJhdGlvbiBieSBhYm91dCAxMCUgZm9yIFBNMi41LCA2JSBmb3IgUE0xMCwgMTMlIGZvciBPMywgMjQlIGZvciBOSDMgYW5kIDMwJSBmb3IgU08yLCBidXQgZGlkIG5vdCBtYXJrZWRseSBjaGFuZ2UgTk8yIGNvbmNlbnRyYXRpb25zLgpodHRwczovL2FpcnF1YWxpdHluZXdzLmNvbS8yMDE4LzA3LzMwL3BsYW50cy1hbmQtdHJlZXMtbm90LXRoZS1zb2x1dGlvbi10by1haXItcG9sbHV0aW9uLWluLWNpdGllcy8KCkNsZWFuaW5nIGRhdGFzZXQgZnVuY3Rpb246CmBgYHtyfQpjbGVhbl9iY25fZGF0YSA8LSBmdW5jdGlvbihkYXRhKSB7CiAgZGF0YSA8LSBkYXRhICU+JSAKICBtdXRhdGUoc2VjdG9yID0gYXMuZmFjdG9yKHN0cl9leHRyYWN0KG5vbV9jYWJpbmEsICIoPzw9Wy1dXFxEKS4qIikpLAogICAgICAgICBxdWFsaXRhdF9haXJlID0gYXMuZmFjdG9yKHF1YWxpdGF0X2FpcmUpLAogICAgICAgICBxdWFsaXRhdF9vMyA9IGFzLmZhY3RvcihxdWFsaXRhdF9vMyksCiAgICAgICAgIHZhbG9yX28zID0gYXMubnVtZXJpYyhzdHJfZXh0cmFjdCh2YWxvcl9vMywgIl5bWzpkaWdpdDpdXSIpKSwKICAgICAgICAgcXVhbGl0YXRfbm8yID0gYXMuZmFjdG9yKHF1YWxpdGF0X25vMiksCiAgICAgICAgIHZhbG9yX25vMiA9IGFzLm51bWVyaWMoc3RyX2V4dHJhY3QodmFsb3Jfbm8yLCAiXltbOmRpZ2l0Ol1dIikpLAogICAgICAgICBxdWFsaXRhdF9wbTEwID0gYXMuZmFjdG9yKHF1YWxpdGF0X3BtMTApLAogICAgICAgICB2YWxvcl9wbTEwID0gYXMubnVtZXJpYyhzdHJfZXh0cmFjdCh2YWxvcl9wbTEwLCAiXltbOmRpZ2l0Ol1dIikpLAogICAgICAgICBkYXRlID0gc3RyX2V4dHJhY3QoZ2VuZXJhdCwgIi4qW1s6c3BhY2U6XV0iKSwKICAgICAgICAgaG91ciA9IHN0cl9leHRyYWN0KGdlbmVyYXQsICIoPzw9W1s6c3BhY2U6XV0pWzAtOS5dKyIpKSAlPiUKICBzZXBhcmF0ZShjb2wgPSBkYXRlLCBpbnRvID0gYygiZGF5IiwgIm1vbnRoIiwgInllYXIiKSwgc2VwID0gIi8iKSAlPiUKICBtdXRhdGUoZGF5ID0gYXMuaW50ZWdlcihkYXkpLAogICAgICAgICBtb250aCA9IGFzLmludGVnZXIobW9udGgpLAogICAgICAgICB5ZWFyID0gYXMuaW50ZWdlcih5ZWFyKSwKICAgICAgICAgaG91ciA9IGFzLmludGVnZXIoaG91ciksCiAgICAgICAgICNzZWN0b3IgPSBjYXNlX3doZW4oc2VjdG9yID09ICJDaXV0YWRlbGxhIiB+IGFzLmZhY3RvcigiQ2l1dGF0IFZlbGxhIiksIFRSVUUgfiBhcy5mYWN0b3Ioc2VjdG9yKSksCiAgICAgICAgIG1vbnRoID0gY2FzZV93aGVuKG1vbnRoID09IDEgfiBhcy5pbnRlZ2VyKDEzKSwgVFJVRSB+IGFzLmludGVnZXIobW9udGgpKSkgJT4lCiAgc2VsZWN0KHNlY3RvciwgcXVhbGl0YXRfYWlyZSwgcXVhbGl0YXRfbzMsIHZhbG9yX28zLCBxdWFsaXRhdF9ubzIsIHZhbG9yX25vMiwgcXVhbGl0YXRfcG0xMCwKICAgICAgICAgdmFsb3JfcG0xMCwgZGF5LCBtb250aCwgeWVhciwgaG91cikKICBkYXRhCn0KYGBgCgpBZ2dyZWdhdGUgZGF0YToKYGBge3J9CmRhdGFfMDZfMjAxOCA8LSB0YmxfZGYoZnJlYWQoImRhdGEvMjAxOF8wNl9KdW55X3F1YWxpdGF0X2FpcmVfQkNOLmNzdiIsIGhlYWRlcj1UUlVFKSkKZGF0YV8wN18yMDE4IDwtIHRibF9kZihmcmVhZCgiZGF0YS8yMDE4XzA3X0p1bGlvbF9xdWFsaXRhdF9haXJlX0JDTi5jc3YiLCBoZWFkZXI9VFJVRSkpCmRhdGFfMDhfMjAxOCA8LSB0YmxfZGYoZnJlYWQoImRhdGEvMjAxOF8wOF9BZ29zdF9xdWFsaXRhdF9haXJlX0JDTi5jc3YiLCBoZWFkZXI9VFJVRSkpCmRhdGFfMDlfMjAxOCA8LSB0YmxfZGYoZnJlYWQoImRhdGEvMjAxOF8wOV9TZXRlbWJyZV9xdWFsaXRhdF9haXJlX0JDTi5jc3YiLCBoZWFkZXI9VFJVRSkpCmRhdGFfMTBfMjAxOCA8LSB0YmxfZGYoZnJlYWQoImRhdGEvMjAxOF8xMF9PY3R1YnJlX3F1YWxpdGF0X2FpcmVfQkNOLmNzdiIsIGhlYWRlcj1UUlVFKSkKZGF0YV8xMl8yMDE4IDwtIHRibF9kZihmcmVhZCgiZGF0YS8yMDE4XzEyX0Rlc2VtYnJlX3F1YWxpdGF0X2FpcmVfQkNOLmNzdiIsIGhlYWRlcj1UUlVFKSkKZGF0YV8xMV8yMDE4IDwtIHRibF9kZihmcmVhZCgiZGF0YS8yMDE4XzExX25vdmVtYnJlX3F1YWxpdGF0X2FpcmVfQkNOLmNzdiIsIGhlYWRlcj1UUlVFKSkKZGF0YV8wMV8yMDE5IDwtIHRibF9kZihmcmVhZCgiZGF0YS8yMDE5XzAxX0dlbmVyX3F1YWxpdGF0X2FpcmVfQkNOLmNzdiIsIGhlYWRlcj1UUlVFKSkKZGF0YSA8LSByYmluZChkYXRhXzA2XzIwMTgsCiAgICAgICAgICAgICAgZGF0YV8wN18yMDE4LAogICAgICAgICAgICAgIGRhdGFfMDhfMjAxOCwKICAgICAgICAgICAgICBkYXRhXzA5XzIwMTgsCiAgICAgICAgICAgICAgZGF0YV8xMF8yMDE4LAogICAgICAgICAgICAgIGRhdGFfMTFfMjAxOCwKICAgICAgICAgICAgICBkYXRhXzEyXzIwMTgsCiAgICAgICAgICAgICAgZGF0YV8wMV8yMDE5KSAlPiUgY2xlYW5fYmNuX2RhdGEoKSAKc3VtbWFyeShkYXRhKQpgYGAKCmBgYHtyfQpwbG90aXQgPC0gZGF0YSAlPiUgCiAgZ2F0aGVyKG1lYXN1cmUsIG1lYXN1cmVfdmFsdWUsIHZhbG9yX28zLCB2YWxvcl9ubzIsIHZhbG9yX3BtMTApICU+JQogIGZpbHRlcih5ZWFyID49IDIwMTgsIG1vbnRoID49IDYsIHNlY3RvciAlaW4lIGMoIkVpeGFtcGxlIiwgIlBhbGF1IFJlaWFsIiwgIlZhbGwgSGVicm9uIikpICU+JQogIHNlbGVjdChtb250aCwgZGF5LCBob3VyLCBtZWFzdXJlLCBtZWFzdXJlX3ZhbHVlLCBzZWN0b3IpICU+JQogIGdyb3VwX2J5KG1vbnRoLCBob3VyLCBtZWFzdXJlLCBzZWN0b3IpICU+JQogIHN1bW1hcmlzZShtZWFuX3ZhbF9ob3VyID0gbWVhbihtZWFzdXJlX3ZhbHVlLCBuYS5ybSA9IFRSVUUpKSAlPiUKICBnZ3Bsb3QoYWVzKGhvdXIsIG1lYW5fdmFsX2hvdXIsIGNvbG9yID0gbWVhc3VyZSkpICsKICBsYWJzKHRpdGxlID0gIsK1Zy9twrMgbWVkaW8gZGUgY29udGFtaW5hZG9yZXMiLAogICAgICAgeCA9ICJIb3JhIiwgCiAgICAgICB5ID0gIsK1Zy9twrMgbWVkaW8iLAogICAgICAgY29sb3IgPSAiQ29udGFtaW5hZG9yIiwKICAgICAgIGNhcHRpb24gPSAiRGF0b3MgZGUgb3BlbmRhdGEtYWp1bnRhbWVudC5iYXJjZWxvbmEuY2F0IikgKwogIHNjYWxlX2NvbG9yX2Rpc2NyZXRlKGxhYmVscyA9IGMoIk5PMiIsICJPMyIsICJQTTEwIikpICsKICBnZW9tX2xpbmUoKSArCiAgZ2VvbV9wb2ludCgpICsgCiAgZmFjZXRfZ3JpZChzZWN0b3IgfiBtb250aCkgKwogIHRoZW1lX21pbmltYWwoKQpgYGAKCmBgYHtyfQooaiA8LSBkYXRhICU+JSAKICBnYXRoZXIobWVhc3VyZSwgbWVhc3VyZV92YWx1ZSwgdmFsb3JfbzMsIHZhbG9yX25vMiwgdmFsb3JfcG0xMCkgJT4lCiAgI2ZpbHRlcih5ZWFyID49IDIwMTgsIG1vbnRoID49IDYsIHNlY3RvciAlaW4lIGMoIkVpeGFtcGxlIiwgIlBhbGF1IFJlaWFsIiwgIlZhbGwgSGVicm9uIikpICU+JQogIGZpbHRlcih5ZWFyID49IDIwMTgsIG1vbnRoID49IDYpICU+JQogIHNlbGVjdChtb250aCwgZGF5LCBob3VyLCBtZWFzdXJlLCBtZWFzdXJlX3ZhbHVlLCBzZWN0b3IpICU+JQogICBtdXRhdGUobWVhc3VyZSA9IGNhc2Vfd2hlbihtZWFzdXJlID09ICJ2YWxvcl9ubzIiIH4gIk5PMiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lYXN1cmUgPT0gInZhbG9yX28zIiB+ICJPMyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lYXN1cmUgPT0gInZhbG9yX3BtMTAiIH4gIlBNMTAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gbWVhc3VyZSkpICU+JQogIGdyb3VwX2J5KG1vbnRoLCBtZWFzdXJlLCBzZWN0b3IpICU+JQogIHN1bW1hcmlzZShtZWFuX3ZhbF9tb250aCA9IG1lYW4obWVhc3VyZV92YWx1ZSwgbmEucm0gPSBUUlVFKSkgJT4lCiAgZ2dwbG90KGFlcyhtb250aCwgbWVhbl92YWxfbW9udGgpKSArCiAgbGFicyh0aXRsZSA9ICJNb250aGx5IGF2ZXJhZ2Ugb2YgcG9sbHV0YW50cyBjb2xvcmVkIGJ5IGRpc3RyaWN0LCBKdW5lIDIwMTggLSBKYW4gMjAxOSIsCiAgICAgICB4ID0gIk1vbnRoIiwgCiAgICAgICB5ID0gIsK1Zy9twrMiLAogICAgICAgY29sb3IgPSAiRGlzdHJpY3QiLAogICAgICAgY2FwdGlvbiA9ICJEYXRhIGZyb20gb3BlbmRhdGEtYWp1bnRhbWVudC5iYXJjZWxvbmEuY2F0IikgKwogICNzY2FsZV9jb2xvcl9kaXNjcmV0ZShsYWJlbHMgPSBjKCJOTzIiLCAiTzMiLCAiUE0xMCIpKSArCiAgZ2VvbV9saW5lKHNpemU9MSwgYWVzKGNvbG9yID0gc2VjdG9yKSkgKwogIGdlb21fc21vb3RoKHNlPUZBTFNFLCBjb2xvcj0iYmxhY2siLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBtZXRob2Q9bG0pICsKICAjZ2VvbV9wb2ludCgpICsgCiAgZmFjZXRfd3JhcCh+IG1lYXN1cmUsIG5jb2wgPSAzKSArCiAgdGhlbWVfbWluZSgpKQoKI21ldGhvZD1sbSBmb3IgZ2VvbV9zbW9vdGgKYGBgCmBgYHtyfQpnZ3Bsb3RseShqKSAKYGBgCmBgYHtyfQpzYXZlV2lkZ2V0KGdncGxvdGx5KGosIGR5bmFtaWNUaWNrcyA9IFRSVUUpLCBmaWxlID0gIm1lYW5ieW1vbnRoMjAxOC5odG1sIikKYGBgCgoKYGBge3J9CmRhdGEgJT4lIAogIGdhdGhlcihtZWFzdXJlLCBtZWFzdXJlX3ZhbHVlLCB2YWxvcl9vMywgdmFsb3Jfbm8yLCB2YWxvcl9wbTEwKSAlPiUKICAjZmlsdGVyKHllYXIgPj0gMjAxOCwgbW9udGggPj0gNiwgc2VjdG9yICVpbiUgYygiRWl4YW1wbGUiLCAiUGFsYXUgUmVpYWwiLCAiVmFsbCBIZWJyb24iKSkgJT4lCiAgZmlsdGVyKHllYXIgPj0gMjAxOCwgbW9udGggPj0gNikgJT4lCiAgc2VsZWN0KG1vbnRoLCBkYXksIGhvdXIsIG1lYXN1cmUsIG1lYXN1cmVfdmFsdWUsIHNlY3RvcikgJT4lCiAgZ3JvdXBfYnkobW9udGgsIG1lYXN1cmUsIHNlY3RvcikgJT4lCiAgc3VtbWFyaXNlKG1lYW5fdmFsX21vbnRoID0gbWVhbihtZWFzdXJlX3ZhbHVlLCBuYS5ybSA9IFRSVUUpKSAlPiUKICBnZ3Bsb3QoYWVzKG1vbnRoLCBtZWFuX3ZhbF9tb250aCwgY29sb3IgPSBtZWFzdXJlKSkgKwogIGxhYnModGl0bGUgPSAiwrVnL23CsyBtZWRpbyBkZSBjb250YW1pbmFkb3JlcyIsCiAgICAgICB4ID0gIk1lcyIsIAogICAgICAgeSA9ICLCtWcvbcKzIG1lZGlvIiwKICAgICAgIGNvbG9yID0gIkNvbnRhbWluYWRvciIsCiAgICAgICBjYXB0aW9uID0gIkRhdG9zIGRlIG9wZW5kYXRhLWFqdW50YW1lbnQuYmFyY2Vsb25hLmNhdCIpICsKICBzY2FsZV9jb2xvcl9kaXNjcmV0ZShsYWJlbHMgPSBjKCJOTzIiLCAiTzMiLCAiUE0xMCIpKSArCiAgZ2VvbV9saW5lKHNpemU9MSkgKwogICNnZW9tX3BvaW50KCkgKyAKICBmYWNldF93cmFwKH4gc2VjdG9yLCBuY29sID0gNCkgKwogIHRoZW1lX21pbmUoKQpgYGAKCmBgYHtyfQoocGxvdGl0IDwtIGRhdGEgJT4lIAogIGdhdGhlcihtZWFzdXJlLCBtZWFzdXJlX3ZhbHVlLCB2YWxvcl9vMywgdmFsb3Jfbm8yLCB2YWxvcl9wbTEwKSAlPiUKICBmaWx0ZXIoeWVhciA+PSAyMDE4LCBtb250aCA+PSA2LCBzZWN0b3IgJWluJSBjKCJFaXhhbXBsZSIsICJQYWxhdSBSZWlhbCIsICJWYWxsIEhlYnJvbiIpKSAlPiUKICBzZWxlY3QobW9udGgsIGRheSwgaG91ciwgbWVhc3VyZSwgbWVhc3VyZV92YWx1ZSwgc2VjdG9yKSAlPiUKICBncm91cF9ieShtb250aCwgc2VjdG9yKSAlPiUKICBzdW1tYXJpc2UobWVhbl92YWxfbW9udGggPSBtZWFuKG1lYXN1cmVfdmFsdWUsIG5hLnJtID0gVFJVRSkpICU+JQogIGdncGxvdChhZXMobW9udGgsIG1lYW5fdmFsX21vbnRoKSkgKwogIGxhYnModGl0bGUgPSAiwrVnL23CsyBtZWRpbyBkZSBjb250YW1pbmFkb3JlcyIsCiAgICAgICB4ID0gIk1lcyIsIAogICAgICAgeSA9ICLCtWcvbcKzIG1lZGlvIiwKICAgICAgIGNhcHRpb24gPSAiRGF0b3MgZGUgb3BlbmRhdGEtYWp1bnRhbWVudC5iYXJjZWxvbmEuY2F0IikgKwogIGdlb21fbGluZSgpICsKICBnZW9tX3BvaW50KCkgKyAKICBmYWNldF93cmFwKH4gc2VjdG9yLCBucm93ID0gNCkgKwogIHRoZW1lX21pbmUoKSkKYGBgCgpgYGB7cn0KbGlicmFyeShwbG90bHkpCmxpYnJhcnkoaHRtbHdpZGdldHMpCnNhdmVXaWRnZXQoZ2dwbG90bHkocGxvdGl0LCBkeW5hbWljVGlja3MgPSBGQUxTRSksIGZpbGUgPSAibWVhbmNvbnQuaHRtbCIpOwpgYGAKCiMjIyBKdXN0IGNsZWFuCmBgYHtyfQpjbGVhbl9kYXRhIDwtIGZ1bmN0aW9uKGRhdGEpIHsKICBkYXRhIDwtIGRhdGEgJT4lIAogIG11dGF0ZShzZWN0b3IgPSBhcy5mYWN0b3Ioc3RyX2V4dHJhY3Qobm9tX2NhYmluYSwgIig/PD1bLV1cXEQpLioiKSksCiAgICAgICAgIHF1YWxpdGF0X2FpcmUgPSBhcy5mYWN0b3IocXVhbGl0YXRfYWlyZSksCiAgICAgICAgIHF1YWxpdGF0X28zID0gYXMuZmFjdG9yKHF1YWxpdGF0X28zKSwKICAgICAgICAgdmFsb3JfbzMgPSBhcy5udW1lcmljKHN0cl9leHRyYWN0KHZhbG9yX28zLCAiXltbOmRpZ2l0Ol1dIikpLAogICAgICAgICBxdWFsaXRhdF9ubzIgPSBhcy5mYWN0b3IocXVhbGl0YXRfbm8yKSwKICAgICAgICAgdmFsb3Jfbm8yID0gYXMubnVtZXJpYyhzdHJfZXh0cmFjdCh2YWxvcl9ubzIsICJeW1s6ZGlnaXQ6XV0iKSksCiAgICAgICAgIHF1YWxpdGF0X3BtMTAgPSBhcy5mYWN0b3IocXVhbGl0YXRfcG0xMCksCiAgICAgICAgIHZhbG9yX3BtMTAgPSBhcy5udW1lcmljKHN0cl9leHRyYWN0KHZhbG9yX3BtMTAsICJeW1s6ZGlnaXQ6XV0iKSksCiAgICAgICAgIGRhdGUgPSBzdHJfZXh0cmFjdChnZW5lcmF0LCAiLipbWzpzcGFjZTpdXSIpLAogICAgICAgICBob3VyID0gc3RyX2V4dHJhY3QoZ2VuZXJhdCwgIig/PD1bWzpzcGFjZTpdXSlbMC05Ll0rIikpICU+JQogIHNlcGFyYXRlKGNvbCA9IGRhdGUsIGludG8gPSBjKCJkYXkiLCAibW9udGgiLCAieWVhciIpLCBzZXAgPSAiLyIpICU+JQogIG11dGF0ZShkYXkgPSBhcy5pbnRlZ2VyKGRheSksCiAgICAgICAgIG1vbnRoID0gYXMuaW50ZWdlcihtb250aCksCiAgICAgICAgIHllYXIgPSBhcy5pbnRlZ2VyKHllYXIpLAogICAgICAgICBob3VyID0gYXMuaW50ZWdlcihob3VyKSwKICAgICAgICAgbW9udGggPSBhcy5pbnRlZ2VyKG1vbnRoKSkgJT4lCiAgc2VsZWN0KHNlY3RvciwgcXVhbGl0YXRfYWlyZSwgcXVhbGl0YXRfbzMsIHZhbG9yX28zLCBxdWFsaXRhdF9ubzIsIHZhbG9yX25vMiwgcXVhbGl0YXRfcG0xMCwKICAgICAgICAgdmFsb3JfcG0xMCwgZGF5LCBtb250aCwgeWVhciwgaG91cikKICBkYXRhCn0KYGBgCgpgYGB7cn0KKHAgPC0gZGF0YV8wNl8yMDE4ICU+JSBjbGVhbl9kYXRhKCkgJT4lCiAgZ2F0aGVyKG1lYXN1cmUsIG1lYXN1cmVfdmFsdWUsIHZhbG9yX28zLCB2YWxvcl9ubzIsIHZhbG9yX3BtMTApICU+JQogIGZpbHRlcih5ZWFyID09IDIwMTgsIG1vbnRoID09IDYpICU+JQogIHNlbGVjdChkYXksIGhvdXIsIG1lYXN1cmUsIG1lYXN1cmVfdmFsdWUsIHNlY3RvcikgJT4lCiAgIG11dGF0ZShtZWFzdXJlID0gY2FzZV93aGVuKG1lYXN1cmUgPT0gInZhbG9yX25vMiIgfiAiTk8yIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVhc3VyZSA9PSAidmFsb3JfbzMiIH4gIk8zIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVhc3VyZSA9PSAidmFsb3JfcG0xMCIgfiAiUE0xMCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiBtZWFzdXJlKSkgJT4lCiAgZ3JvdXBfYnkoaG91ciwgbWVhc3VyZSwgc2VjdG9yKSAlPiUKICBzdW1tYXJpc2UobWVhbl92YWxfaG91ciA9IG1lYW4obWVhc3VyZV92YWx1ZSwgbmEucm0gPSBUUlVFKSkgJT4lCiAgIAogICAKICAgCiAgZ2dwbG90KGFlcyhob3VyLCBtZWFuX3ZhbF9ob3VyLCBjb2xvciA9IG1lYXN1cmUpKSArCiAgbGFicyh0aXRsZSA9ICJNZWFuIHZhbHVlIG9mIHBvbGx1dGFudHMgYnkgaG91ciBpbiBKdW5lIDIwMTgiLAogICAgICAgeCA9ICJIb3VyIiwgCiAgICAgICB5ID0gIsK1Zy9twrMiLAogICAgICAgY29sb3IgPSAiUG9sbHV0YW50IiwKICAgICAgIGNhcHRpb24gPSAiRGF0YSBmcm9tIG9wZW5kYXRhLWFqdW50YW1lbnQuYmFyY2Vsb25hLmNhdCIpICsKICAjc2NhbGVfY29sb3JfZGlzY3JldGUobGFiZWxzID0gYygiTk8yIiwgIk8zIiwgIlBNMTAiKSkgKwogIGdlb21fbGluZShzaXplPTEpICsKICAjZ2VvbV9wb2ludCgpICsgCiAgZmFjZXRfd3JhcCh+IHNlY3RvciwgbnJvdyA9IDIpICsKICB0aGVtZV9taW5lKCkKICApCmBgYAoKYGBge3J9CnNhdmVXaWRnZXQoZ2dwbG90bHkocCwgZHluYW1pY1RpY2tzID0gVFJVRSksIGZpbGUgPSAibWVhbmp1bi5odG1sIikKYGBgCgpgYGB7cn0KZ2dwbG90bHkocCkgCgpgYGAKCgoKCgoKCgoKCgoKCgoKCiMjIyBNb3J0YWxpdGF0CmBgYHtyfQptb3J0YWxpdGF0IDwtIHRibF9kZihmcmVhZCgiMjAxOF90YXhhX21vcnRhbGl0YXQuY3N2IiwgaGVhZGVyPVRSVUUpKQptb3J0YWxpdGF0ICU+JQogIHNlbGVjdChOb21fZGlzdHJpY3RlLCBOb21fYmFycmksIE5vbWJyZSkgJT4lCiAgZ3JvdXBfYnkoTm9tX2Rpc3RyaWN0ZSkgJT4lCiAgc3VtbWFyaXNlKG1lYW5fbiA9IG1lYW4oTm9tYnJlKSkgJT4lCiAgZ2dwbG90KCkgKwogIGdlb21fYmFyKGFlcyh4ID0gTm9tX2Rpc3RyaWN0ZSwgeSA9IG1lYW5fbiksc3RhdCA9ICJpZGVudGl0eSIpCmBgYAoKCmBgYHtyfQp0aGVtZV9taW5lIDwtIGZ1bmN0aW9uICgpIHsgCiAgICB0aGVtZV9idyhiYXNlX3NpemU9MTIsIGJhc2VfZmFtaWx5PSJNb250c2VycmF0IikgJStyZXBsYWNlJSAKICAgICAgICB0aGVtZSgKICAgICAgICAgICAgcGFuZWwuYmFja2dyb3VuZCAgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgICAgIHBsb3QuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsPSIjZWJmZmY1IiwgY29sb3VyPU5BKSwgCiAgICAgICAgICAgIGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGw9InRyYW5zcGFyZW50IiwgY29sb3VyPU5BKSwKICAgICAgICAgICAgbGVnZW5kLmtleSA9IGVsZW1lbnRfcmVjdChmaWxsPSJ0cmFuc3BhcmVudCIsIGNvbG91cj1OQSkKICAgICAgICApCn0KYGBgCgoKYGBge3J9CmRhdGFfMDZfMjAxOSA8LSB0YmxfZGYoZnJlYWQoImRhdGEvMjAxOV8wNl9qdW55X3F1YWxpdGF0X2FpcmVfQkNOLmNzdiIsIGhlYWRlcj1UUlVFKSkKZGF0YV8wNF8yMDE5IDwtIHRibF9kZihmcmVhZCgiZGF0YS8yMDE5XzA0X0FicmlsX3F1YWxpdGF0X2FpcmVfQkNOLmNzdiIsIGhlYWRlcj1UUlVFKSkKI3N1bW1hcnkoZGF0YV8wNl8yMDE5KQpgYGAKCgpgYGB7cn0KbGVuZ3RoKG5hbWVzKGRhdGFfMDRfMjAxOSkpCihpIDwtIGRhdGFfMDRfMjAxOSAlPiUKICBzZWxlY3QoNTo1NykgJT4lCiAgbXV0YXRlKG1lYXN1cmUgPSBhcy5mYWN0b3IoY2FzZV93aGVuKENPRElfQ09OVEFNSU5BTlQgPT0gMSB+ICJTTzIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDT0RJX0NPTlRBTUlOQU5UID09IDcgfiAiTk8iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDT0RJX0NPTlRBTUlOQU5UID09IDggfiAiTk8yIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ09ESV9DT05UQU1JTkFOVCA9PSAxMiB+ICJOT3giLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDT0RJX0NPTlRBTUlOQU5UID09IDE0IH4gIk8zIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ09ESV9DT05UQU1JTkFOVCA9PSA2IH4gIkNPIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ09ESV9DT05UQU1JTkFOVCA9PSAxMCB+ICJQTTEwIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSB+ICIiKSkpICU+JQogIG11dGF0ZShzZWN0b3IgPSBhcy5mYWN0b3IoY2FzZV93aGVuKEVTVEFDSU8gPT0gNCB+ICJQb2JsZW5vdSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEVTVEFDSU8gPT0gNDIgfiAiU2FudHMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBFU1RBQ0lPID09IDQzIH4gIkVpeGFtcGxlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRVNUQUNJTyA9PSA0NCB+ICJHcsOgY2lhIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRVNUQUNJTyA9PSA1MCB+ICJDaXV0YWRlbGxhIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRVNUQUNJTyA9PSA1NCB+ICJWYWxsIEhlYnJvbiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEVTVEFDSU8gPT0gNTcgfiAiUGFsYXUgUmVpYWwiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gIiIpKSkgJT4lCiAgZ2F0aGVyKGhvdXIsIG1lYXN1cmVfdmFsdWUsIHN0YXJ0c193aXRoKCJIIikpICU+JQogIGdhdGhlcih2YWxpZGF0aW9uLCB2YWwsIHN0YXJ0c193aXRoKCJWIikpICU+JSBkaXN0aW5jdCgpICU+JQogIG11dGF0ZShkYXkgPSBhcy5pbnRlZ2VyKERJQSksCiAgICAgICAgIG1vbnRoID0gYXMuaW50ZWdlcihNRVMpLAogICAgICAgICB5ZWFyID0gYXMuaW50ZWdlcihBTlkpLAogICAgICAgICBob3VyID0gYXMuaW50ZWdlcihzdHJfZXh0cmFjdChob3VyLCIuLiQiKSkpICU+JQogIHNlbGVjdChzZWN0b3IsIHllYXIsIG1vbnRoLCBkYXksIGhvdXIsIG1lYXN1cmUsIG1lYXN1cmVfdmFsdWUpICU+JQogICNmaWx0ZXIoc2VjdG9yID09ICJDaXV0YWRlbGxhIikgJT4lCiAgZ3JvdXBfYnkoaG91ciwgbWVhc3VyZSwgc2VjdG9yKSAlPiUKICBzdW1tYXJpc2UobWVhbl92YWxfaG91ciA9IG1lYW4obWVhc3VyZV92YWx1ZSwgbmEucm0gPSBUUlVFKSkgJT4lCiAgICAKICBnZ3Bsb3QoYWVzKGhvdXIsIG1lYW5fdmFsX2hvdXIsIGNvbG9yID0gbWVhc3VyZSkpICsKICBsYWJzKHRpdGxlID0gIk1lYW4gdmFsdWUgb2YgcG9sbHV0YW50cyBieSBob3VyIGluIEFwcmlsIDIwMTkiLAogICAgICAgeCA9ICJIb3VyIiwgCiAgICAgICB5ID0gIsK1Zy9twrMiLAogICAgICAgY29sb3IgPSAiUG9sbHV0YW50IiwKICAgICAgIGNhcHRpb24gPSAiRGF0YSBmcm9tIG9wZW5kYXRhLWFqdW50YW1lbnQuYmFyY2Vsb25hLmNhdCIpICsKICAjc2NhbGVfY29sb3JfZGlzY3JldGUobGFiZWxzID0gYygiTk8yIiwgIk8zIiwgIlBNMTAiKSkgKwogICNzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygicHVycGxlIiwgInllbGxvdyIsICJyZWQiLCAib3JhbmdlIiwgImdyZWVuIiwgImJsdWUiLCAicGluayIpKSArCiAgZ2VvbV9saW5lKHNpemU9MSkgKwogICNnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSA5MCwgbGluZXR5cGUgPSAyLCBjb2xvciA9ICJyZWQiKSArCiAgI2dlb21faGxpbmUoeWludGVyY2VwdCA9IDExMCwgbGluZXR5cGUgPSAyLCBjb2xvciA9ICJncmVlbiIpICsKICAjZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMjAwLCBsaW5ldHlwZSA9IDIsIGNvbG9yID0gInBpbmsiKSArCiAgI2dlb21fdGV4dChhZXMoMCw5MCxsYWJlbCA9ICJMaW1pdCBOTzIgYnkgaCIsIHZqdXN0ID0gLTEpLCBjb2xvciA9ICJibGFjayIpICsKICAjZ2VvbV9wb2ludCgpICsgCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgMjIpKSArIAogIGZhY2V0X3dyYXAofiBzZWN0b3IsIG5yb3cgPSAxKSArCiAgdGhlbWVfbWluZSgpKQoKICAKYGBgCgpgYGB7cn0KZ2dwbG90bHkoaSkgCmBgYApgYGB7cn0Kc2F2ZVdpZGdldChnZ3Bsb3RseShpLCBkeW5hbWljVGlja3MgPSBUUlVFKSwgZmlsZSA9ICJtZWFuYXByMTkuaHRtbCIpCmBgYAoKCmBgYHtyfQphcHJpbDE5IDwtIGRhdGFfMDRfMjAxOSAlPiUKICBzZWxlY3QoNTo1NykgJT4lCiAgbXV0YXRlKG1lYXN1cmUgPSBhcy5mYWN0b3IoY2FzZV93aGVuKENPRElfQ09OVEFNSU5BTlQgPT0gMSB+ICJTTzIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDT0RJX0NPTlRBTUlOQU5UID09IDcgfiAiTk8iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDT0RJX0NPTlRBTUlOQU5UID09IDggfiAiTk8yIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ09ESV9DT05UQU1JTkFOVCA9PSAxMiB+ICJOT3giLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDT0RJX0NPTlRBTUlOQU5UID09IDE0IH4gIk8zIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ09ESV9DT05UQU1JTkFOVCA9PSA2IH4gIkNPIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ09ESV9DT05UQU1JTkFOVCA9PSAxMCB+ICJQTTEwIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSB+ICIiKSkpICU+JQogIG11dGF0ZShzZWN0b3IgPSBhcy5mYWN0b3IoY2FzZV93aGVuKEVTVEFDSU8gPT0gNCB+ICJQb2JsZW5vdSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEVTVEFDSU8gPT0gNDIgfiAiU2FudHMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBFU1RBQ0lPID09IDQzIH4gIkVpeGFtcGxlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRVNUQUNJTyA9PSA0NCB+ICJHcsOgY2lhIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRVNUQUNJTyA9PSA1MCB+ICJDaXV0YWRlbGxhIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRVNUQUNJTyA9PSA1NCB+ICJWYWxsIEhlYnJvbiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEVTVEFDSU8gPT0gNTcgfiAiUGFsYXUgUmVpYWwiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gIiIpKSkgJT4lCiAgZ2F0aGVyKGhvdXIsIG1lYXN1cmVfdmFsdWUsIHN0YXJ0c193aXRoKCJIIikpICU+JQogIGdhdGhlcih2YWxpZGF0aW9uLCB2YWwsIHN0YXJ0c193aXRoKCJWIikpICU+JSBkaXN0aW5jdCgpICU+JQogIG11dGF0ZShkYXkgPSBhcy5pbnRlZ2VyKERJQSksCiAgICAgICAgIG1vbnRoID0gYXMuaW50ZWdlcihNRVMpLAogICAgICAgICB5ZWFyID0gYXMuaW50ZWdlcihBTlkpLAogICAgICAgICBob3VyID0gYXMuaW50ZWdlcihzdHJfZXh0cmFjdChob3VyLCIuLiQiKSkpICU+JQogIHNlbGVjdChzZWN0b3IsIHllYXIsIG1vbnRoLCBkYXksIGhvdXIsIG1lYXN1cmUsIG1lYXN1cmVfdmFsdWUpCgoKanVuZTE5IDwtIGRhdGFfMDZfMjAxOSAlPiUKICBzZWxlY3QoNTo1NykgJT4lCiAgbXV0YXRlKG1lYXN1cmUgPSBhcy5mYWN0b3IoY2FzZV93aGVuKENPRElfQ09OVEFNSU5BTlQgPT0gMSB+ICJTTzIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDT0RJX0NPTlRBTUlOQU5UID09IDcgfiAiTk8iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDT0RJX0NPTlRBTUlOQU5UID09IDggfiAiTk8yIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ09ESV9DT05UQU1JTkFOVCA9PSAxMiB+ICJOT3giLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDT0RJX0NPTlRBTUlOQU5UID09IDE0IH4gIk8zIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ09ESV9DT05UQU1JTkFOVCA9PSA2IH4gIkNPIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ09ESV9DT05UQU1JTkFOVCA9PSAxMCB+ICJQTTEwIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSB+ICIiKSkpICU+JQogIG11dGF0ZShzZWN0b3IgPSBhcy5mYWN0b3IoY2FzZV93aGVuKEVTVEFDSU8gPT0gNCB+ICJQb2JsZW5vdSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEVTVEFDSU8gPT0gNDIgfiAiU2FudHMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBFU1RBQ0lPID09IDQzIH4gIkVpeGFtcGxlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRVNUQUNJTyA9PSA0NCB+ICJHcsOgY2lhIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRVNUQUNJTyA9PSA1MCB+ICJDaXV0YWRlbGxhIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRVNUQUNJTyA9PSA1NCB+ICJWYWxsIEhlYnJvbiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEVTVEFDSU8gPT0gNTcgfiAiUGFsYXUgUmVpYWwiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gIiIpKSkgJT4lCiAgZ2F0aGVyKGhvdXIsIG1lYXN1cmVfdmFsdWUsIHN0YXJ0c193aXRoKCJIIikpICU+JQogIGdhdGhlcih2YWxpZGF0aW9uLCB2YWwsIHN0YXJ0c193aXRoKCJWIikpICU+JSBkaXN0aW5jdCgpICU+JQogIG11dGF0ZShkYXkgPSBhcy5pbnRlZ2VyKERJQSksCiAgICAgICAgIG1vbnRoID0gYXMuaW50ZWdlcihNRVMpLAogICAgICAgICB5ZWFyID0gYXMuaW50ZWdlcihBTlkpLAogICAgICAgICBob3VyID0gYXMuaW50ZWdlcihzdHJfZXh0cmFjdChob3VyLCIuLiQiKSkpICU+JQogIHNlbGVjdChzZWN0b3IsIHllYXIsIG1vbnRoLCBkYXksIGhvdXIsIG1lYXN1cmUsIG1lYXN1cmVfdmFsdWUpCgpkYXRhMTkgPC0gcmJpbmQoYXByaWwxOSwganVuZTE5KQpzdW1tYXJ5KGRhdGExOSkKYGBgCgpgYGB7cn0KKGsgPC0gZGF0YTE5ICU+JSAKICBmaWx0ZXIoeWVhciA+PSAyMDE5LCBtb250aCA+PSA0KSAlPiUKICBncm91cF9ieShtb250aCwgbWVhc3VyZSwgc2VjdG9yKSAlPiUKICBzdW1tYXJpc2UobWVhbl92YWxfbW9udGggPSBtZWFuKG1lYXN1cmVfdmFsdWUsIG5hLnJtID0gVFJVRSkpICU+JQogICNzZWxlY3QobW9udGgsIGRheSwgaG91ciwgbWVhc3VyZSwgbWVhc3VyZV92YWx1ZSwgc2VjdG9yKSAlPiUKICBnZ3Bsb3QoYWVzKG1vbnRoLCBtZWFuX3ZhbF9tb250aCkpICsKICBsYWJzKHRpdGxlID0gIk1vbnRobHkgYXZlcmFnZSBvZiBwb2xsdXRhbnRzIGNvbG9yZWQgYnkgZGlzdHJpY3QsIEFwcmlsIDIwMTkgLSBKdW5lIDIwMTkiLAogICAgICAgeCA9ICJNb250aCIsIAogICAgICAgeSA9ICLCtWcvbcKzIiwKICAgICAgIGNvbG9yID0gIkRpc3RyaWN0IiwKICAgICAgIGNhcHRpb24gPSAiRGF0YSBmcm9tIG9wZW5kYXRhLWFqdW50YW1lbnQuYmFyY2Vsb25hLmNhdCIpICsKICAjc2NhbGVfY29sb3JfZGlzY3JldGUobGFiZWxzID0gYygiTk8yIiwgIk8zIiwgIlBNMTAiKSkgKwogIGdlb21fbGluZShzaXplPTEsIGFlcyhjb2xvciA9IHNlY3RvcikpICsKICAjZ2VvbV9zbW9vdGgoc2U9RkFMU0UsIGNvbG9yPSJibGFjayIsIGxpbmV0eXBlID0gImRhc2hlZCIsIG1ldGhvZD1sbSkgKwogICNnZW9tX3BvaW50KCkgKyAKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gYyg0LDYpKSArCiAgZmFjZXRfd3JhcCh+IG1lYXN1cmUsIG5jb2wgPSA3KSArCiAgdGhlbWVfbWluZSgpKQoKI21ldGhvZD1sbSBmb3IgZ2VvbV9zbW9vdGgKYGBgCgpgYGB7cn0KZ2dwbG90bHkoaykgCmBgYAoKYGBge3J9CnNhdmVXaWRnZXQoZ2dwbG90bHkoaywgZHluYW1pY1RpY2tzID0gVFJVRSksIGZpbGUgPSAibWVhbjE5Lmh0bWwiKQpgYGAKCgpgYGB7cn0KYWNjaWRlbnRzMTggPC0gdGJsX2RmKGZyZWFkKCJkYXRhLzIwMThfYWNjaWRlbnRzX2NhdXNlc19ndV9iY24uY3N2IixoZWFkZXI9VFJVRSkpCnN1bW1hcnkoYWNjaWRlbnRzMTgpCmhlYWQoYWNjaWRlbnRzMTgpCmBgYApgYGB7cn0KKGFjPC0gYWNjaWRlbnRzMTggJT4lIGZpbHRlcihNZXNfYW55ID49IDYsIEFueSA9PSAyMDE4KSAlPiUKICBtdXRhdGUoc2VjdG9yID0gY2FzZV93aGVuKE5vbV9kaXN0cmljdGUgPT0gIkRlc2NvbmVndXQiIH4gYXMuY2hhcmFjdGVyKE5BKSxUUlVFIH4gYXMuY2hhcmFjdGVyKE5vbV9kaXN0cmljdGUpKSwKICAgICAgICAgc2VjdG9yID0gYXMuZmFjdG9yKHNlY3RvciksCiAgICAgICAgIHllYXIgPSBBbnksCiAgICAgICAgIG1vbnRoID0gTWVzX2FueSwKICAgICAgICAgZGF5ID0gRGlhX21lcywKICAgICAgICAgaG91ciA9IEhvcmFfZGlhKSAlPiUKICAgZHJvcF9uYSgpICU+JQogIHNlbGVjdChzZWN0b3IsIHllYXIsIG1vbnRoLCBkYXksIGhvdXIpKQpsZXZlbHMoYWMkc2VjdG9yKQpgYGAKCmBgYHtyfQphYyAlPiUKICBncm91cF9ieShzZWN0b3IsIG1vbnRoLCBob3VyKSAlPiUKICBzdW1tYXJpemUoaW5jaWRlbnRzID0gbigpKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBob3VyLCB5ID0gaW5jaWRlbnRzLCBjb2xvciA9IGZhY3Rvcihtb250aCkpKSArCiAgZ2VvbV9saW5lKCkgKwogIGdlb21fc21vb3RoKHNlID0gRkFMU0UsIHNpemUgPSAxLCBjb2xvciA9ICJibGFjayIpICsKICAjZ2VvbV9wb2ludCgpICsgCiAgZmFjZXRfd3JhcCh+IHNlY3RvciwgbmNvbCA9IDUpICsKICB0aGVtZV9taW5pbWFsKCkKICAKYGBgCgoKYGBge3J9CmFjICU+JQogIGdyb3VwX2J5KHNlY3RvciwgaG91cikgJT4lCiAgc3VtbWFyaXplKGluY2lkZW50cyA9IG4oKSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gaG91ciwgeSA9IGluY2lkZW50cywgY29sb3IgPSBzZWN0b3IpKSArCiAgZ2VvbV9saW5lKCkgKwogIGdlb21fc21vb3RoKHNlID0gRkFMU0UsIHNpemUgPSAxLCBjb2xvciA9ICJibGFjayIpICsKICAjZ2VvbV9wb2ludCgpICsgCiAgI2ZhY2V0X3dyYXAofiBzZWN0b3IsIG5jb2wgPSA1KSArCiAgdGhlbWVfbWluaW1hbCgpCiAgCmBgYAoKYGBge3J9CmFjICU+JQogIGdyb3VwX2J5KHNlY3RvciwgbW9udGgpICU+JQogIHN1bW1hcml6ZShpbmNpZGVudHMgPSBuKCkpICU+JQogIGdncGxvdChhZXMoeCA9IG1vbnRoLCB5ID0gaW5jaWRlbnRzLCBjb2xvciA9IHNlY3RvcikpICsKICBnZW9tX2xpbmUoKSArCiAgZ2VvbV9zbW9vdGgoc2UgPSBGQUxTRSwgc2l6ZSA9IDEsIGNvbG9yID0gImJsYWNrIikgKwogICNnZW9tX3BvaW50KCkgKyAKICAjZmFjZXRfd3JhcCh+IHNlY3RvciwgbmNvbCA9IDUpICsKICB0aGVtZV9taW5pbWFsKCkKICAKYGBgCgoKCgo=